

import { callRecursively, flatten } from "../arrays";
import { ensureUnit, toNameParams } from "../strings";
import { AnimationConfig, AnimationDefinition } from "./types";
import { isObject } from "../types";
import defaultAnimations from "./defaultAnimations";

/**
 * 可修改的动画配置数组
 * @description 包含所有动画（默认动画和自定义动画）的配置项，使用 {@link registerAnimation} 注册的动画会被添加到数组中
 */
export let animations = [...defaultAnimations];

/**
 * 解析动画属性
 * @description 解析动画配置，将字符串或数组转换为动画属性数组
 * @param {string | (string | Partial<AnimationDefinition>)[] | Partial<AnimationDefinition>} animation - 动画配置
 * @returns {Partial<AnimationDefinition>[]} 解析后的动画属性数组
 * @example
 * parseAnimationProps('fadeIn|duration:1s|easing:ease-in-out');
 * // [{ name: 'fadeIn', params: { duration: '1s', easing: 'ease-in-out' } }]
 */
export function parseAnimationProps(animation: string | (string | Partial<AnimationDefinition>)[] | Partial<AnimationDefinition>): Partial<AnimationDefinition>[] {
  return flatten(callRecursively(animation, (item) => {
    if ('string' === typeof item) {
      return toNameParams(item);
    } else if (isObject(item, true)) {
      // 处理对象类型的动画配置
      const { name, params = {}, ...rest } = item as Partial<AnimationDefinition>;
      // 合并params和rest属性
      const newParams = { ...params, ...rest };
      return { name, params: newParams };
    } else {
      // 不是对象类型，直接返回
      return item;
    }
  }));
}

/**
 * 动画样式生成器（需注册过的动画）
 * @description 将注册过的动画的配置和参数转换为标准化的动画样式对象（带css变量）
 * @param {string | (string | Partial<AnimationDefinition>)[] | Partial<AnimationDefinition>} animation - 动画配置
 * @param {Record<string, string | number | boolean>} params - 动画参数
 * @returns {Record<string, string | number>} 标准化的动画样式对象
 * @example
 * useAnimationStyle('fadeIn|duration:1s|easing:ease-in-out', { opacity: 0 });
 * // {
 * //   animationName: 'fadeIn',
 * //   animationDuration: '1s',
 * //   animationTimingFunction: 'ease-in-out',
 * //   animationDelay: '0s',
 * //   opacity: 0
 * // }
 */
export function useAnimationStyle(
  animation: string | (string | Partial<AnimationDefinition>)[] | Partial<AnimationDefinition>,
  params?: Record<string, string | number | boolean>
) {
  // 解析动画配置
  let animationPropsList = parseAnimationProps(animation);

  // 从animations中匹配对应的项，并覆盖属性，同时过滤掉未启用的动画
  const enabledAnims = animationPropsList
    .map(prop => {
      const baseAnim = animations.find((a) => {
        if (a.name === prop.name) return true;

        if (prop.name?.includes('.')) {
          const [name] = prop.name!.split('.');
          if (name === a.name) return true;
        }

        return false;
      });

      if (!baseAnim) return null;

      // 合并基础动画配置和用户提供的配置
      return { ...baseAnim, ...prop } as AnimationConfig;
    })
    .filter((anim): anim is AnimationConfig => anim !== null);

  if (enabledAnims.length === 0) return {};

  let animationStyle: Record<string, string | number> = {
    animationName: enabledAnims.map(anim => {
      if (typeof anim.keyframes! === 'object') {
        if (anim.name.includes('.')) {
          const [name, key] = anim.name.split('.');
          // 检查key是否存在于keyframes中，如果不存在则使用第一个
          if (key && Object.keys(anim.keyframes!).includes(key)) {
            return name + '_' + key;
          } else {
            const firstKey = Object.keys(anim.keyframes!)[0];
            return name + '_' + firstKey;
          }
        } else {
          // 默认使用第一个
          const firstKey = Object.keys(anim.keyframes!)[0];
          return anim.name + '_' + firstKey;
        }
      }
      return anim.name;
    }).join(', '),
    animationDuration: enabledAnims.map(anim => anim.duration).join(', '),
    animationTimingFunction: enabledAnims.map(anim => anim.timingFunction).join(', '),
    animationDelay: enabledAnims.map(anim => anim.delay).join(', '),
    animationIterationCount: enabledAnims.map(anim => anim.iterationCount).join(', '),
    animationComposition: enabledAnims.map(anim => anim.composition || 'replace').join(', '),
  };

  // 处理每个动画的params，将其设置为CSS变量
  enabledAnims.forEach(anim => {
    let name = anim.name;
    if (anim.name.includes('.')) {
      [name] = anim.name.split('.');
    }

    // 处理动画自身的params
    if (anim.params && typeof anim.params === 'object') {
      Object.keys(anim.params).forEach(key => {
        if (['duration', 'delay'].includes(key)) {
          animationStyle[`--tui-animation-${name}-${key}`] = ensureUnit(anim.params![key] as string | number, 's');
        } else {
          animationStyle[`--tui-animation-${name}-${key}`] = anim.params![key] as string | number;
        }
      });
    }

    // 处理全局params
    if (params) {
      if (undefined !== params.duration) {
        animationStyle[`--tui-animation-${name}-duration`] = ensureUnit(params.duration as string | number, 's');
      }
      if (undefined !== params.delay) {
        animationStyle[`--tui-animation-${name}-delay`] = ensureUnit(params.delay as string | number, 's');
      }
      if (undefined !== params.iterationCount) {
        if (false === params.iterationCount) {
          animationStyle[`--tui-animation-${name}-iterationCount`] = '0';
        } else if ('infinite' === params.iterationCount || true === params.iterationCount) {
          animationStyle[`--tui-animation-${name}-iterationCount`] = 'infinite';
        } else {
          animationStyle[`--tui-animation-${name}-iterationCount`] = params.iterationCount;
        }
      }
    }
  });

  return animationStyle;
}

/**
 * 安装动画关键帧到文档中
 * @description 在文档中创建并插入包含所有动画关键帧的style元素
 */
export function installKeyFrames() {
  // 注册关键帧
  const style = document.createElement('style');
  // 只生成关键帧，不生成类选择器
  style.textContent = animations.map(anim => {
    if ('object' === typeof anim.keyframes) {
      // 如果keyframes是对象，则遍历对象
      return Object.entries(anim.keyframes).map(([key, frameContent]) => {
        // 如果frameContent已经包含@keyframes，则直接使用
        if (frameContent.includes('@keyframes')) {
          return frameContent;
        }
        // 否则按当前逻辑处理
        return `
        @keyframes ${anim.name}_${key} {
          ${frameContent.trim()}
        }
          `;
      }).join('');
    } else {
      // 保持原有逻辑
      return `
        @keyframes ${anim.name} {
          ${anim.keyframes!.trim()}
        }
      `;
    }
  }).join('');
  document.head.appendChild(style);
}

/**
 * 全局注册动画配置
 * @description 将自定义动画配置注册到全局动画列表中，已存在的动画会被覆盖
 * @param {...AnimationDefinition} animationConfigs - 一个或多个动画配置对象
 * @example
 * registerAnimation({
 *   name: 'fadeIn',
 *   keyframes: {
 *     '0%': { opacity: 0 },
 *     '100%': { opacity: 1 }
 *   }
 * });
 */
export function registerAnimation(...animationConfigs: AnimationDefinition[]) {
  animationConfigs.forEach(config => {
    // 检查是否已存在同名动画
    const index = animations.findIndex(a => a.name === config.name);
    if (index >= 0) {
      // 存在则覆盖
      animations[index] = config;
    } else {
      // 不存在则添加
      animations.push(config);
    }
  });
}

/**
 * 暂停元素的动画
 * @param {HTMLElement} el - 要暂停动画的DOM元素
 * @description 将指定元素的动画播放状态设置为'paused'
 */
export function animationPause(el: HTMLElement) {
  el.style.animationPlayState = 'paused';
}

/**
 * 恢复元素的动画
 * @param {HTMLElement} el - 要恢复动画的DOM元素
 * @description 将指定元素的动画播放状态设置为'running'
 */
export function animationResume(el: HTMLElement) {
  el.style.animationPlayState = 'running';
}

/**
 * 停止元素的动画
 * @param {HTMLElement} el - 要停止动画的DOM元素
 * @description 暂停动画并将迭代次数设置为0，完全停止动画效果
 */
export function animationStop(el: HTMLElement) {
  el.style.animationPlayState = 'paused';
  el.style.animationIterationCount = '0';
}

/**
 * 重新开始元素的动画
 * @param {HTMLElement} el - 要重新开始动画的DOM元素
 * @description 通过重置动画名称并强制重绘来重新开始元素的动画
 */
export function animationRestart(el: HTMLElement) {
  const originalAnimationName = el.style.animationName;

  // 设置动画为none以停止当前动画
  el.style.animationName = 'none';

  // 强制重绘
  el.offsetHeight;

  // 恢复原始动画
  el.style.animationName = originalAnimationName || '';
}